package com.atguigu.dga.governance.assess.impl.storage;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.dga.governance.assess.Assessor;
import com.atguigu.dga.governance.bean.AssessParam;
import com.atguigu.dga.governance.bean.GovernanceAssessDetail;
import com.atguigu.dga.meta.bean.TableMetaInfo;
import com.atguigu.dga.meta.constants.MetaConst;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

//两个表字段重复超过{percent}%，则给0分，其余给10分   比的是相同层级的表
@Component("TABLE_SIMILAR")
public class TableSimilarAssessor extends Assessor {
    @Override
    protected void assess(AssessParam assessParam, GovernanceAssessDetail governanceAssessDetail) throws ParseException {
  /*      获取自己表的 字段    获取表名   获取层级
        获取其他所有表的 字段  获取表名  获取层级   思路一：在当前考评方法中 每拿到一张表 去就查询全表进行比对 每一张表查一次
                                               思路二：提前把所有表的信息查询出来 给到考评去用 只查一次*/

        //0.创建集合
        HashSet<String> similarSet = new HashSet<>();

        //1.获取自己表（考评表）的表名
        TableMetaInfo curTableMetaInfo = assessParam.getTableMetaInfo();
        String curFullTableName = curTableMetaInfo.getSchemaName() + "." + curTableMetaInfo.getTableName();
        //获取考评表的列
        String curColJsonStr = curTableMetaInfo.getColNameJson();
        //将这个json字符串转为 List<JsonObject>
        List<JSONObject> curColJsonList = JSON.parseArray(curColJsonStr, JSONObject.class);
        //获取当前表的层级
        String curDwLevel = curTableMetaInfo.getTableMetaInfoExtra().getDwLevel();
        //2.获取所有表的数据
        Map<String, TableMetaInfo> otherTableMetaInfoMap = assessParam.getTableMetaInfoMap();
        //3.遍历这个map集合拿到每张表 然后和当前考评表一一对比
        for (Map.Entry<String, TableMetaInfo> otherEntry : otherTableMetaInfoMap.entrySet()) {
            String otherFullTbaleName = otherEntry.getKey();
            TableMetaInfo otherTableMetaInfo = otherEntry.getValue();
            //获取对比表的层级
            String otherDwLevel = otherTableMetaInfo.getTableMetaInfoExtra().getDwLevel();
            //获取对比表的col集合
            String otherColJsonStr = otherTableMetaInfo.getColNameJson();
            List<JSONObject> otherColJsonList = JSON.parseArray(otherColJsonStr, JSONObject.class);

            //4.进行比对  不能和自己的表比对 其次要和同层的比 ods层的数据不比

            if (!curDwLevel.equals(MetaConst.DW_LEVEL_ODS) //ods层的数据不比
                    && curDwLevel.equals(otherDwLevel) //其次要和同层的比
                    && !curFullTableName.equals(otherFullTbaleName) //不能和自己的表比对
            ) {

                //定义一个累加器用来记录这两张表相同字段的个数
                Integer similarCount = 0;

                //获取考评表的每个字段  遍历
                for (JSONObject curJsonObj : curColJsonList) {
                    //获取对比表的每个字段  遍历
                    for (JSONObject otherJsonObj : otherColJsonList) {
                        //获取当前表的字段名
                        String curColNameStr = curJsonObj.getString("name");
                        //获取对比表的字段名
                        String otherColNameStr = otherJsonObj.getString("name");

                        if(curColNameStr.equals(otherColNameStr)){
//                            similarCount=similarCount+1;
//                            similarCount += 1;
                            similarCount++;
                        }
                    }
                }

                //5.和指标参数中定义的阈值做对比
                //获取阈值
                String metricParamsJsonStr = assessParam.getGovernanceMetric().getMetricParamsJson();
                JSONObject metricParamJsonObj = JSON.parseObject(metricParamsJsonStr);
                BigDecimal metricRatio = metricParamJsonObj.getBigDecimal("percent");

                //计算相同字段的占比   相同字段的个数/考评表的总字段个数
                BigDecimal curRatio = BigDecimal.valueOf(similarCount).divide(BigDecimal.valueOf(curColJsonList.size()), 2, RoundingMode.HALF_UP).movePointRight(2);

                //拿当前占比和阈值做对比
                if (curRatio.compareTo(metricRatio)>0){
                    similarSet.add(otherFullTbaleName);
                }
            }
        }

        //根据Set集合中元素的个数判读是否有相似的表
        if (similarSet.size()>0){
            //有相似表
            governanceAssessDetail.setAssessScore(BigDecimal.ZERO);
            governanceAssessDetail.setAssessProblem("存在相似表："+similarSet);
        }

    }
}
